package cn.edu.lingnan.service.impl;

import cn.edu.lingnan.service.PaperExportService;
import cn.edu.lingnan.service.PaperService;
import cn.edu.lingnan.user.dtos.PromptDto;
import cn.edu.lingnan.user.vos.OptionVO;
import cn.edu.lingnan.user.vos.PaperWithQuestionVo;
import cn.edu.lingnan.user.vos.QuestionVO;
import cn.edu.lingnan.utils.AIChatUtils;
import cn.edu.lingnan.utils.OpenAIChatStreaming;
import cn.edu.lingnan.utils.TextExtractorUtils;
import jakarta.servlet.ServletOutputStream;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class PaperExportServiceImpl implements PaperExportService {
    @Autowired
    private PaperService paperService;


    @Autowired
    private TextExtractorUtils textExtractorUtils;

    @Autowired
    private AIChatUtils aiChatUtils;

    @Override
    public void exportPaper(Integer paperId, OutputStream outputStream) {
        PaperWithQuestionVo paper = paperService.getPaperWithQuestionVo(paperId);
        if (paper == null) {
            throw new RuntimeException("Paper not found");
        }
        // 打印试卷信息
        log.info("试卷信息,{}", paper);

        try (XWPFDocument document = new XWPFDocument()) {
            // 添加标题
            XWPFParagraph title = document.createParagraph();
            title.setAlignment(ParagraphAlignment.CENTER);
            XWPFRun titleRun = title.createRun();
            titleRun.setBold(true);
            titleRun.setFontSize(16);
            titleRun.setText(paper.getPaperName());
            // 添加空行
            document.createParagraph();
            document.createParagraph();
            // 添加考生信息（标题下方）
            addStudentInfoSection(document);
            document.createParagraph();
            // 添加题目
            addQuestions(document, paper.getQuestions());


            // 保存 DOCX
            document.write(outputStream);
        } catch (IOException e) {
            throw new RuntimeException("Error generating paper document", e);
        }
    }

    @Override
    public String generatePaper(PromptDto generatePaperDto, ServletOutputStream outputStream, MultipartFile word, MultipartFile image) {
        // 从word和image中提取文本
        String KnowledgeCitations = extractText(word, image);
        log.info("KnowledgeCitations:{}", KnowledgeCitations);
        generatePaperDto.setKnowledgePoint(KnowledgeCitations);
        // 构建提示
        String prompt = createrompt(generatePaperDto);
        log.info("prompt:{}", prompt);
        String result = aiChatUtils.processChat(prompt);
//        String result = null;
//        try {
//            result = OpenAIChatStreaming.chatStream(prompt);
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }
        log.info("call:{}", result);

        // 将HTML内容写入输出流
        try {
            outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            log.error("Failed to write HTML content to output stream", e);
        }
        return result;

    }



    private String extractText(MultipartFile word, MultipartFile image) {
        String KnowledgeCitations = "";
                if(word!=null){
            try {
                String extractedFromWord = textExtractorUtils.extractFromWord(word);
                KnowledgeCitations+=extractedFromWord;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        if(image!=null){
            try {
                String extractedFromImage = textExtractorUtils.extractFromImage(image);
                KnowledgeCitations+=extractedFromImage;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return KnowledgeCitations;
    }

    private String createrompt(PromptDto generatePaperDto) {
        StringBuilder prompt = new StringBuilder();

        // 基础试卷信息
        prompt.append("\n请根据以下要求生成一份标准试卷：\n\n");
        prompt.append("### 试卷基本信息\n");
        prompt.append("1. 试卷名称：").append(generatePaperDto.getPaperName()).append("\n");
        prompt.append("2. 试卷总分：").append(generatePaperDto.getPaperScore()).append("分\n");
        prompt.append("3. 难度等级：").append(difficultyLevelToText(generatePaperDto.getDifficulty())).append("\n");

        if(generatePaperDto.getRole() != null){
            prompt.append("4. 我的身份是：").append(generatePaperDto.getRole()).append("\n");
        }

        // 题型配置
        prompt.append("\n### 题型配置（按题目数量排序）\n");
        appendQuestionType(prompt, "单选题", generatePaperDto.getChoiceNum(), generatePaperDto.getChoiceScore());
        appendQuestionType(prompt, "多选题", generatePaperDto.getMultiChoiceNum(), generatePaperDto.getMultiChoiceScore());
        appendQuestionType(prompt, "判断题", generatePaperDto.getTrialNum(), generatePaperDto.getTrialScore());
        appendQuestionType(prompt, "填空题", generatePaperDto.getFillNum(), generatePaperDto.getFillScore());
        appendQuestionType(prompt, "简答题", generatePaperDto.getShortAnswerNum(), generatePaperDto.getShortAnswerScore());
        appendQuestionType(prompt, "其他题型", generatePaperDto.getOtherNum(), generatePaperDto.getOtherScore());

        // 答案与解析要求
        prompt.append("\n### 附加要求\n");
        if (generatePaperDto.getNeedAnswer() != null && generatePaperDto.getNeedAnswer() == 1) {
            prompt.append("- 需要提供题目答案\n");
        }
        if (generatePaperDto.getNeedExplain() != null && generatePaperDto.getNeedExplain() == 1) {
            prompt.append("- 需要提供答案解析\n");
        }

        // 知识点引用
        if (!generatePaperDto.getKnowledgePoint().isEmpty()) {
            prompt.append("\n### 知识点要求\n");
            prompt.append("请严格基于以下知识点命题：\n");
            prompt.append(generatePaperDto.getKnowledgePoint());
        }

        // 格式与结构要求
        prompt.append("\n### 格式规范\n");
        prompt.append("1.返回html源码,html和css在同一个文件\n");
        prompt.append("2. 答案和解析放在题目后面,是生成完所有题目后再生成答案和解析，答案和题目是分开的\n");
        prompt.append("3. 居中显示");
        prompt.append("4.考生信息，格式调整为（居中）：学院__________ 班级________  学号___________  姓名_________ ");
        prompt.append("5.生成的数学符号可以直接显示的，不需要借助额外的库");
        prompt.append("6.单选题别漏了选项");
        prompt.append("7.需要严格按照我的要求来生成");


        // 备注信息
        if (generatePaperDto.getRemark() != null && !generatePaperDto.getRemark().isEmpty()) {
            prompt.append("\n### 特别说明\n").append(generatePaperDto.getRemark());
        }

        return prompt.toString();
    }

    private void appendQuestionType(StringBuilder sb, String typeName, Integer num, Integer score) {
        if (num != null && num > 0 && score != null && score > 0) {
            sb.append("- ").append(typeName).append("：")
                    .append(num).append("道（")
                    .append(score).append("分），")
                    .append("每题").append(score / num).append("分\n");
        }
    }

    private String difficultyLevelToText(Integer difficulty) {
        if (difficulty == null) return "未指定";
        return switch (difficulty) {
            case 1 -> "基础级（适合初学者）";
            case 2 -> "入门级（基础应用）";
            case 3 -> "进阶级（综合应用）";
            case 4 -> "挑战级（复杂场景）";
            case 5 -> "专家级（创新题型）";
            default -> "自定义难度（" + difficulty + "）";
        };
    }

    /**
     * 考生信息，格式调整为：
     * 学院__________ 班级________  学号___________  姓名_________
     */
    private void addStudentInfoSection(XWPFDocument document) {
        XWPFParagraph infoParagraph = document.createParagraph();
        XWPFRun infoRun = infoParagraph.createRun();
        infoRun.setFontSize(12);
        infoRun.setText("       \t\t学院__________ 班级________  学号___________  姓名_________");
    }

    /**
     * 添加题目，并在题目旁边加上该题的分值
     */
    private void addQuestions(XWPFDocument document, List<QuestionVO> questions) {
        Map<Integer, String> typeMap = Map.of(
                1, "单选题",
                2, "多选题",
                3, "判断题",
                4, "填空题",
                5, "简答题"
        );

        Map<Integer, List<QuestionVO>> groupedQuestions = questions.stream()
                .collect(Collectors.groupingBy(QuestionVO::getQuestionType));

        for (int type : List.of(1, 2, 3, 4, 5)) {
            List<QuestionVO> questionList = groupedQuestions.getOrDefault(type, new ArrayList<>());
            if (!questionList.isEmpty()) {
                // 题目类型标题
                XWPFParagraph sectionTitle = document.createParagraph();
                sectionTitle.setSpacingBefore(200);
                XWPFRun sectionRun = sectionTitle.createRun();
                sectionRun.setBold(true);
                sectionRun.setFontSize(14);
                sectionRun.setText(typeMap.get(type));

                for (int i = 0; i < questionList.size(); i++) {
                    QuestionVO question = questionList.get(i);

                    // 题目
                    XWPFParagraph questionPara = document.createParagraph();
                    XWPFRun questionRun = questionPara.createRun();
                    questionRun.setFontSize(12);
                    questionRun.setText((i + 1) + ". " + question.getQuestionName() + "  (" + question.getQuestionScore() + " 分)");

                    // 选项（如果有）
                    for (OptionVO option : question.getOptions()) {
                        XWPFParagraph optionPara = document.createParagraph();
                        XWPFRun optionRun = optionPara.createRun();
                        optionRun.setFontSize(12);
                        optionRun.setText(option.getOptionKey() + ". " + option.getOptionValue());
                    }
                }
            }
        }
    }
}
